package org.swingplus.core.scanner;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.swingplus.core.annotation.listeners.KeyListener;
import org.swingplus.core.annotation.listeners.Listener;
import org.swingplus.core.annotation.listeners.MouseListener;
import org.swingplus.core.annotation.listeners.MouseMotionListener;
import org.swingplus.core.annotation.widget.Frame;
import org.swingplus.core.bean.MetaData;
import org.swingplus.core.util.AnnoManageUtil;
import org.swingplus.core.widget.WidgetActvity;

import java.awt.event.ActionListener;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.util.List;
import java.util.Map;

public class ListenerScan extends ComponentScan {
	private static final Logger logger = LoggerFactory.getLogger(ListenerScan.class);


	public static void listenerScan(List<Object> objs) {

		for (Object obj:objs){
			listenerScan(obj);
		}

	}

	public static void listenerScan(Object obj) {
		for (Method method : obj.getClass().getDeclaredMethods()) {
//			MouseListener ann = method.getAnnotation(MouseListener.class);
//			MouseListener ann = method.getAnnotation(MouseListener.class);
			Annotation[] annotations = method.getAnnotations();
			for (Annotation ann:annotations){
				//logger.warn("annotation Superclass: {}",annotation.annotationType().getSuperclass());
				Annotation anns =ann.annotationType().getAnnotation(Listener.class);
				if(null!=anns){
					logger.warn("注解上有Listener注解");
					if (ann != null) {
						String value = null;
						Model model=new Model();
						if(ann.annotationType()==MouseListener.class){
//							value = ;
							model.setValues(((MouseListener)ann).value());
							model.setClazz(((MouseListener)ann).beanType());
							
						}else if(ann.annotationType()==KeyListener.class){
							model.setValues(((KeyListener)ann).value());
							model.setClazz(((KeyListener)ann).beanType());
//							value = ((KeyListener)ann).value();
//							addListener(value,obj,obj,method,ann);
						}else if(ann.annotationType()==MouseMotionListener.class){
							model.setValues(((MouseMotionListener)ann).value());
							model.setClazz(((MouseMotionListener)ann).beanType());
//							value = ((MouseMotionListener)ann).value();
//							addListener(value,obj,obj,method,ann);
						}
						addListener(model,obj,obj,method,ann);
					}
				}

			}
		}
	}
	
	
	public static void addListener(Model model,final Object obj, final Object source, final Method method, Annotation ann)
			 {
		//TODO 如果value是空 给当前类 下面的也封装一个方法
		String value=model.getValues();
		if(("").equals(value)) {
			try {
				addListener(obj, method,ann.annotationType().getSimpleName());
			} catch (Exception e) {
				e.printStackTrace();
			}
		}else {
			String[] values = value.split(",");
			for (String val : values) {
				try {
					Field field = obj.getClass().getDeclaredField(val);
					if (!field.isAccessible()) {
						field.setAccessible(true);
						addListener(obj, field.get(obj),model.getClazz(), method,ann.annotationType());
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	public static void addListener(final Object obj, final Object source,Class classEventName, final Method m, Class annoType)
			throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
		Object listener = null;
		@SuppressWarnings("rawtypes")
		Class returnType = m.getReturnType();
		String methodName = "add" + annoType.getSimpleName();
		if (returnType == Void.class) {
			try {
				listener = Proxy.newProxyInstance(obj.getClass().getClassLoader(),
						new Class[] { classEventName }, new InvocationHandler() {
							@Override
							public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
								if (m.getParameterTypes().length == 0) {
									return m.invoke(obj);
								}
								return m.invoke(obj, args);
							}
						});
			} catch (IllegalArgumentException  | SecurityException e) {
				e.printStackTrace();
			}
			source.getClass().getMethod(methodName,classEventName).invoke(source, listener);
		}
//		else if (returnType == java.util.EventListener.class) {
		else {
			if (m.getParameterTypes().length == 0) {
				listener = m.invoke(obj);
			} else {
				listener = m.invoke(obj, source);
			}
			source.getClass().getMethod(methodName, returnType).invoke(source, listener);
		}
	}
	
	
	public static void addListener(final Object obj, final Method m, String eventName)
			throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
		Object listener = null;
		@SuppressWarnings("rawtypes")
		Class returnType = m.getReturnType();
		if (m.getParameterTypes().length == 0) {
			listener = m.invoke(obj);
		}
//			listener = m.invoke(obj, source);
//		} 
//		else {
//			logger.error(" returnType unknown ");
//		}
		String methodName = "add" + eventName;
		 obj.getClass().getMethod(methodName,returnType).invoke(obj, listener);
	}
	

	/**
	 * 采用代理的形式注入相关的方法
	 * 
	 * @param source
	 * @param param
	 * @param m
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 */
	public static void addListener2(Object source, final Object param, final Method m) throws SecurityException,
			NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {

		InvocationHandler handler = new InvocationHandler() {
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				return m.invoke(param);
			}
		};
		Object listener = Proxy.newProxyInstance(null, new Class[] { ActionListener.class }, handler);
		Method addr = source.getClass().getMethod("addActionListener", ActionListener.class);
		addr.invoke(source, listener);
	}
	

}

class Model{
	private Class clazz;
	
	private String values;

	public Class getClazz() {
		return clazz;
	}

	public void setClazz(Class<?> clazz) {
		this.clazz = clazz;
	}

	public String getValues() {
		return values;
	}

	public void setValues(String values) {
		this.values = values;
	}
	
	
	
	
}
